/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ceair.flight.refund.service.uatp.impl;

import com.ceair.flight.refund.dto.appmoblie.RefundApplyDto;
import com.ceair.flight.refund.dto.appmoblie.RefundTktDto;
import com.ceair.flight.refund.dto.external.BasePageQueryReq;
import com.ceair.flight.refund.dto.uatp.PaginationResultRes;
import com.ceair.flight.refund.dto.uatp.RefundApplyDetail;
import com.ceair.flight.refund.dto.uatp.RefundApplyDtoList;
import com.ceair.flight.refund.location.dt.enums.ApplyReason;
import com.ceair.flight.refund.location.dt.enums.RefundResConst;
import com.ceair.flight.refund.location.dt.enums.RefundStatus;
import com.ceair.flight.refund.service.external.IQueryService;
import com.ceair.flight.refund.service.external.ITicketOperation;
import com.ceair.flight.refund.service.uatp.IApplyQuery;
import com.ceair.flight.refund.util.Constants;
import com.ceair.muibe.provider.tkt.DetrTktInfo;
import com.ceair.muservice.common.dto.page.PaginationResult;
import com.ceair.muservice.common.exception.MuServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author youguilin
 */
@Service("facadeRefundApplyQueryImpl")
public class ApplyQueryImpl implements IApplyQuery {

    private static final Logger LOG = LoggerFactory.getLogger(ApplyQueryImpl.class);
    @Autowired
    private IQueryService queryService;

    @Autowired
    private ITicketOperation ticketOperation;

    private static final RefundStatus[] FIRST_AUDIT_STATUS_LIST = new RefundStatus[]{RefundStatus.WAIT_FIRST_AUDIT, RefundStatus.FIRST_AUDIT_EXCEPTION, RefundStatus.SECOND_AUDIT_REFUSE};
    private static final RefundStatus[] SECOND_AUDIT_STATUS_LIST = new RefundStatus[]{RefundStatus.WAIT_SECOND_AUDIT};

    private static Set<RefundStatus> firstStatus;
    private static Set<RefundStatus> secondStatus;

    public ApplyQueryImpl() {
        firstStatus = new HashSet<>(3);
        firstStatus.addAll(Arrays.asList(FIRST_AUDIT_STATUS_LIST));
        secondStatus = new HashSet<>(1);
        secondStatus.addAll(Arrays.asList(SECOND_AUDIT_STATUS_LIST));
    }

    @Override
    public RefundApplyDetail getRefundApplyDetails(long applyId) {
        LOG.info("Querying refund apply detail and detr with id {}", applyId);
        RefundApplyDetail detail = getApplyDetailsWithoutDetr(applyId);
        RefundApplyDto applyDto = detail.getDto();
        if (applyDto == null) {
            return detail;
        }
        RefundTktDto refundTkt = applyDto.getRefundTkt();
        if(refundTkt.getTktPrice()!= null) {
			 BigDecimal tktPrice = refundTkt.getTktPrice();
			 if(refundTkt.getRescheduleGap()!= null) {
				 tktPrice.add(refundTkt.getRescheduleGap());
			 }
			 if(refundTkt.getRescheduleFee()!= null) {
				 tktPrice.add(refundTkt.getRescheduleFee());
			 }
			 if(refundTkt.getRefundFee()!= null) {
				 tktPrice.subtract(refundTkt.getRefundFee());
			 }
			 if(refundTkt.getRefundTax()!= null) {
				 tktPrice.add(refundTkt.getRefundTax());
			 } 
			 refundTkt.setTktPrice(tktPrice);
        }
        applyDto.setRefundTkt(refundTkt);
        String ticketNo = applyDto.getTicketNo();
        try {
            String originalInfo = "";
            String channelCode = applyDto.getRefundTkt().getChannelNo();
            if (ticketNo.contains("/")) {
                String[] ticketNos = ticketNo.split("/");
                for (String tktNo : ticketNos) {
                    ticketOperation.setChannelCode(tktNo, channelCode);
                    DetrTktInfo detrTktInfo = ticketOperation.detrTkt(tktNo);
                    if (!originalInfo.isEmpty()) {
                        originalInfo += "<br><br>";
                    }
                    originalInfo += detrTktInfo.getOriginalInfo();
                }
            } else {
                ticketOperation.setChannelCode(ticketNo, channelCode);
                DetrTktInfo detrTktInfo = ticketOperation.detrTkt(ticketNo);
                originalInfo = detrTktInfo.getOriginalInfo();
            }
            detail.setDetrInfoStr(originalInfo);
        } catch (Exception ex) {
            LOG.error("Get ticket {} Detr detail error", ticketNo, ex);
            detail.setDetrInfoStr("Not available");
        }
        return detail;
    }
    
    public RefundApplyDetail getRfdApplyDetials(long applyId) {
    	 LOG.info("Querying refund apply detail and detr with id {}", applyId);
         RefundApplyDetail detail = getApplyDetailsWithoutDetr(applyId);
         RefundApplyDto applyDto = detail.getDto();
         if (applyDto == null) {
             return detail;
         }
         RefundTktDto refundTkt = applyDto.getRefundTkt();  
         if(refundTkt.getTktPrice()!= null) {
 			 BigDecimal tktPrice = refundTkt.getTktPrice();
 			 if(refundTkt.getRescheduleGap()!= null) {
 				 tktPrice.add(refundTkt.getRescheduleGap());
 			 }
 			 if(refundTkt.getRescheduleFee()!= null) {
 				 tktPrice.add(refundTkt.getRescheduleFee());
 			 }
 			 if(refundTkt.getRefundFee()!= null) {
 				 tktPrice.subtract(refundTkt.getRefundFee());
 			 }
 			 if(refundTkt.getRefundTax()!= null) {
 				 tktPrice.add(refundTkt.getRefundTax());
 			 } 
         }

         String ticketNo = applyDto.getTicketNo();
         try {
             String originalInfo = "";
             String channelCode = applyDto.getRefundTkt().getChannelNo();
             if (ticketNo.contains("/")) {
                 String[] ticketNos = ticketNo.split("/");
                 for (String tktNo : ticketNos) {
                     ticketOperation.setChannelCode(tktNo, channelCode);
                     DetrTktInfo detrTktInfo = ticketOperation.detrTkt(tktNo);
                     if (!originalInfo.isEmpty()) {
                         originalInfo += "<br><br>";
                     }
                     originalInfo += detrTktInfo.getOriginalInfo();
                 }
             } else {
                 ticketOperation.setChannelCode(ticketNo, channelCode);
                 DetrTktInfo detrTktInfo = ticketOperation.detrTkt(ticketNo);
                 originalInfo = detrTktInfo.getOriginalInfo();
             }
             detail.setDetrInfoStr(originalInfo);
             detail.setResultCode(Constants.SUCCESS_CODE);
             detail.setResultMsg(Constants.SUCCESS_MSG);
         } catch (MuServiceException ex) {
        	 detail.setResultCode(ex.getMessage());
         } catch (Exception ex) {
        	 detail.setResultCode(RefundResConst.AIRREFUND_NULL_CODE);
        	 detail.setResultMsg(RefundResConst.AIRREFUND_NULL_MSG + detail.getTransactionId());
         }
         return detail;
    }

    @Override
    public RefundApplyDetail getApplyDetailsWithoutDetr(long applyId) {
        LOG.debug("Getting refund apply detail by id {}", applyId);
        RefundApplyDto dto = queryService.loadDetail(applyId);
        RefundApplyDetail detail = new RefundApplyDetail(dto);
        return detail;
    }

    @Override
    public PaginationResult<RefundApplyDto> getFirstAuditList(BasePageQueryReq pageQueryReq) {
        LOG.debug("Get first audit list with condition: {}", pageQueryReq);
        Set<RefundStatus> statusList = pageQueryReq.getRefundslist();
        if (statusList == null || statusList.isEmpty()) {
            pageQueryReq.setRefundslist(firstStatus);
        }
        Set<ApplyReason> reasons = pageQueryReq.getReasons();
        if (reasons == null || reasons.isEmpty()) {
            pageQueryReq.setReasons(new HashSet(Arrays.asList(ApplyReason.AUDITABLE_REASON)));
        }
        return queryService.loadByPage(pageQueryReq);
    }


    @Override
    public PaginationResult<RefundApplyDto> getSecondAuditList(BasePageQueryReq pageQueryReq) {
        LOG.debug("Get second audit list with condition: {}", pageQueryReq);
        Set<RefundStatus> statusList = pageQueryReq.getRefundslist();
        if (statusList == null || statusList.isEmpty()) {
            pageQueryReq.setRefundslist(secondStatus);
        }
        Set<ApplyReason> reasons = pageQueryReq.getReasons();
        if (reasons == null || reasons.isEmpty()) {
            pageQueryReq.setReasons(new HashSet(Arrays.asList(ApplyReason.AUDITABLE_REASON)));
        }
        return queryService.loadByPage(pageQueryReq);
    }

    @Override
    public List<RefundApplyDto> getRefundApplyByTkt(Set<String> ticketNo) {
        if (ticketNo == null || ticketNo.isEmpty()) {
            LOG.error("Query refund apply list with null ticket Nos, returning null");
            throw new NullPointerException("Query parameter ticket Nos is null");
        }
        LOG.debug("Get refund apply list with ticket No: {}", Arrays.toString(ticketNo.toArray()));
        return queryService.loadDetailByTkt(ticketNo);
    }
    

    @Override
    public PaginationResult<RefundApplyDto> getList(BasePageQueryReq pageQueryReq) {
        LOG.debug("Get refund apply list with condition: {}", pageQueryReq);
        return queryService.loadByPage(pageQueryReq);
    }

	@Override
	public RefundApplyDetail getRfdApplyDetailsWithoutDetr(long applyId) {
		 LOG.debug("Getting refund apply detail by id {}", applyId);
	        RefundApplyDto dto = null;
	        RefundApplyDetail detail = null;
			try {
				dto = queryService.loadDetail(applyId);
				detail.setResultCode(Constants.SUCCESS_CODE);
				detail.setResultMsg(Constants.SUCCESS_MSG);
			} catch (MuServiceException e) {
	        	 detail.setResultCode(e.getMessage());
			}catch (Exception e) {
	       	    detail.setResultCode(RefundResConst.AIRREFUNDAPPLY_NULL_CODE);
	       	    detail.setResultMsg(RefundResConst.AIRREFUNDAPPLY_NULL_MSG + detail.getTransactionId());
			}
	        detail = new RefundApplyDetail(dto);
	        return detail;
	}

	@Override
	public PaginationResultRes getFirAuditList(BasePageQueryReq pageQueryReq) {
		 PaginationResultRes paginationResultRes = new PaginationResultRes();
    	 LOG.debug("Get first audit list with condition: {}", pageQueryReq);
         Set<RefundStatus> statusList = pageQueryReq.getRefundslist();
         if (statusList == null || statusList.isEmpty()) {
             pageQueryReq.setRefundslist(firstStatus);
         }
         Set<ApplyReason> reasons = pageQueryReq.getReasons();
         if (reasons == null || reasons.isEmpty()) {
             pageQueryReq.setReasons(new HashSet(Arrays.asList(ApplyReason.AUDITABLE_REASON)));
         }
         
         try {
			PaginationResult<RefundApplyDto> loadByPage = queryService.loadByPage(pageQueryReq);
			paginationResultRes.setResult(loadByPage);
			paginationResultRes.setResultCode(Constants.SUCCESS_CODE);
			paginationResultRes.setResultMsg(Constants.SUCCESS_MSG);
		} catch (MuServiceException e) {
			paginationResultRes.setResultCode(e.getMessage());
		}catch (Exception e) {
			
       	    paginationResultRes.setResultCode(RefundResConst.AIR_FIR_APPLY_NULL_CODE);
       	    paginationResultRes.setResultMsg(RefundResConst.AIR_FIR_APPLY_NULL_MSG + paginationResultRes.getTransactionId());
		}
        return paginationResultRes;
	}

	@Override
	public PaginationResultRes getSecAuditList(BasePageQueryReq pageQueryReq) {
		LOG.debug("Get second audit list with condition: {}", pageQueryReq);
        PaginationResultRes paginationResultRes = new PaginationResultRes();
        Set<RefundStatus> statusList = pageQueryReq.getRefundslist();
        if (statusList == null || statusList.isEmpty()) {
            pageQueryReq.setRefundslist(secondStatus);
        }
        Set<ApplyReason> reasons = pageQueryReq.getReasons();
        if (reasons == null || reasons.isEmpty()) {
            pageQueryReq.setReasons(new HashSet(Arrays.asList(ApplyReason.AUDITABLE_REASON)));
        }try {
			PaginationResult<RefundApplyDto> loadByPage = queryService.loadByPage(pageQueryReq);
			paginationResultRes.setResult(loadByPage);
			paginationResultRes.setResultCode(Constants.SUCCESS_CODE);
			paginationResultRes.setResultCode(Constants.SUCCESS_MSG);
		} catch (MuServiceException e) {
			paginationResultRes.setResultCode(e.getMessage());
		} catch (Exception e) {
       	    paginationResultRes.setResultCode(RefundResConst.AIR_SEC_APPLY_NULL_CODE);
       	    paginationResultRes.setResultMsg(RefundResConst.AIR_SEC_APPLY_NULL_MSG + paginationResultRes.getTransactionId());
		}
        return paginationResultRes;
	}

	@Override
	public PaginationResultRes getApplyList(BasePageQueryReq pageQueryReq) {
		LOG.debug("Get refund apply list with condition: {}", pageQueryReq);
        PaginationResultRes paginationResultRes = new PaginationResultRes();
        try {
			PaginationResult<RefundApplyDto> loadByPage = queryService.loadByPage(pageQueryReq);
			paginationResultRes.setResult(loadByPage);
			paginationResultRes.setResultCode(Constants.SUCCESS_CODE);
			paginationResultRes.setResultCode(Constants.SUCCESS_MSG);
		} catch (MuServiceException e) {
			paginationResultRes.setResultCode(e.getMessage());
		} catch (Exception e) {
       	    paginationResultRes.setResultCode(RefundResConst.AIRAPPLY_LIST_CODE);
       	    paginationResultRes.setResultMsg(RefundResConst.AIRAPPLY_LIST_MSG + paginationResultRes.getTransactionId());
		}  
        return paginationResultRes;
	}

	@Override
	public RefundApplyDtoList getRfdApplyByTkt(Set<String> ticketNo) {
		 if (ticketNo == null || ticketNo.isEmpty()) {
	            LOG.error("Query refund apply list with null ticket Nos, returning null");
	            throw new NullPointerException("Query parameter ticket Nos is null");
	        }
	        LOG.debug("Get refund apply list with ticket No: {}", Arrays.toString(ticketNo.toArray()));
	        RefundApplyDtoList refundApplyDtoList = new RefundApplyDtoList();
	        try {
				List<RefundApplyDto> loadDetailByTkt = queryService.loadDetailByTkt(ticketNo);
				refundApplyDtoList.setList(loadDetailByTkt);
				refundApplyDtoList.setResultCode(Constants.SUCCESS_CODE);
				refundApplyDtoList.setResultMsg(Constants.SUCCESS_MSG);
			} catch (MuServiceException e) {
				String errorCode = e.getMessage();
				refundApplyDtoList.setResultCode(errorCode);
			} catch (Exception e) {
	       	    refundApplyDtoList.setResultCode(RefundResConst.AIRAPPLY_NULL_CODE);
	       	    refundApplyDtoList.setResultMsg(RefundResConst.AIRAPPLY_NULL_MSG + refundApplyDtoList.getTransactionId()  );
			}
	        return refundApplyDtoList;  
	}
}
